home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!ames!apple!sun-barr!newstop!sun!swap!page
- From: page%swap@Sun.COM (Bob Page)
- Newsgroups: comp.sources.amiga
- Subject: v89i222: rcs - revision control system, Part07/14
- Message-ID: <128098@sun.Eng.Sun.COM>
- Date: 19 Nov 89 09:25:07 GMT
- Sender: news@sun.Eng.Sun.COM
- Lines: 2809
- Approved: page@sun.com
-
- Submitted-by: rsbx@cbmvax.commodore.com (Raymond S. Brand)
- Posting-number: Volume 89, Issue 222
- Archive-name: unix/rcs.07
-
- # This is a shell archive.
- # Remove anything above and including the cut line.
- # Then run the rest of the file through 'sh'.
- # Unpacked files will be owned by you and have default permissions.
- #----cut here-----cut here-----cut here-----cut here----#
- #!/bin/sh
- # shar: SHell ARchive
- # Run the following text through 'sh' to create:
- # rcs/rcs.rcsfiles/partime.c,v
- # rcs/rcs.rcsfiles/rcs.c,v
- # This is archive 7 of a 14-part kit.
- # This archive created: Sun Nov 19 01:12:08 1989
- if `test ! -d rcs`
- then
- mkdir rcs
- echo "mkdir rcs"
- fi
- if `test ! -d rcs/rcs.rcsfiles`
- then
- mkdir rcs/rcs.rcsfiles
- echo "mkdir rcs/rcs.rcsfiles"
- fi
- echo "extracting rcs/rcs.rcsfiles/partime.c,v"
- sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/partime.c,v
- Xhead 1.4;
- Xbranch 1.4.2;
- Xaccess ;
- Xsymbols amiga_rcs:1.4.2 cbmvax_source:1.4.1 uunet_june89_dist:1.4;
- Xlocks ; strict;
- Xcomment @ * @;
- X
- X
- X1.4
- Xdate 89.05.01.14.48.46; author narten; state Exp;
- Xbranches 1.4.1.1 1.4.2.1;
- Xnext ;
- X
- X1.4.1.1
- Xdate 89.08.11.01.41.57; author rsbx; state Exp;
- Xbranches ;
- Xnext ;
- X
- X1.4.2.1
- Xdate 89.10.13.19.17.41; author rsbx; state Exp;
- Xbranches ;
- Xnext 1.4.2.2;
- X
- X1.4.2.2
- Xdate 89.10.15.15.43.31; author rsbx; state Exp;
- Xbranches ;
- Xnext 1.4.2.3;
- X
- X1.4.2.3
- Xdate 89.10.29.14.47.46; author rsbx; state Exp;
- Xbranches ;
- Xnext ;
- X
- X
- Xdesc
- X@Parse date/time string into a TM structure.
- X@
- X
- X
- X
- X1.4
- Xlog
- X@checked in with -k by rsbx at 89.08.10.16.06.05.
- X@
- Xtext
- X@/*
- X * PARTIME parse date/time string into a TM structure
- X *
- X * Usage:
- X * #include "time.h" -- expanded tm structure
- X * char *str; struct tm *tp;
- X * partime(str,tp);
- X * Returns:
- X * 0 if parsing failed
- X * else time values in specified TM structure (unspecified values
- X * set to TMNULL)
- X * Notes:
- X * This code is quasi-public; it may be used freely in like software.
- X * It is not to be sold, nor used in licensed software without
- X * permission of the author.
- X * For everyone's benefit, please report bugs and improvements!
- X * Copyright 1980 by Ken Harrenstien, SRI International.
- X * (ARPANET: KLH @@ SRI)
- X */
- X
- X/* Hacknotes:
- X * If parsing changed so that no backup needed, could perhaps modify
- X * to use a FILE input stream. Need terminator, though.
- X * Perhaps should return 0 on success, else a non-zero error val?
- X * Flush AMPM from TM structure and handle locally within PARTIME,
- X * like midnight/noon?
- X */
- X
- X#ifndef lint
- Xstatic char rcsid[]=
- X"$Header: /usr/src/local/bin/rcs/src/RCS/partime.c,v 1.4 89/05/01 14:48:46 narten Exp $";
- X#endif
- X
- X/* $Log: partime.c,v $
- X * Revision 1.4 89/05/01 14:48:46 narten
- X * fixed #ifdef DEBUG construct
- X *
- X * Revision 1.3 88/11/08 12:02:15 narten
- X * changes from eggert@@sm.unisys.com (Paul Eggert)
- X *
- X * Revision 1.3 88/08/28 14:53:40 eggert
- X * Remove unportable "#endif XXX"s.
- X *
- X * Revision 1.2 87/03/27 14:21:53 jenkins
- X * Port to suns
- X *
- X * Revision 1.1 84/01/23 14:50:07 kcs
- X * Initial revision
- X *
- X * Revision 1.1 82/05/06 11:38:26 wft
- X * Initial revision
- X *
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "time.h"
- X
- X#ifndef lint
- Xstatic char timeid[] = TIMEID;
- X#endif
- X
- Xstruct tmwent {
- X char *went;
- X long wval; /* must be big enough to hold pointer or integer */
- X char wflgs;
- X char wtype;
- X};
- X /* wflgs */
- X#define TWSPEC 01 /* Word wants special processing */
- X#define TWTIME 02 /* Word is a time value (absence implies date) */
- X#define TWDST 04 /* Word is a DST-type timezone */
- X#define TW1200 010 /* Word is NOON or MIDNIGHT (sigh) */
- X
- Xint pt12hack();
- Xint ptnoise();
- Xstruct tmwent tmwords [] = {
- X {"january", 0, 0, TM_MON},
- X {"february", 1, 0, TM_MON},
- X {"march", 2, 0, TM_MON},
- X {"april", 3, 0, TM_MON},
- X {"may", 4, 0, TM_MON},
- X {"june", 5, 0, TM_MON},
- X {"july", 6, 0, TM_MON},
- X {"august", 7, 0, TM_MON},
- X {"september", 8, 0, TM_MON},
- X {"october", 9, 0, TM_MON},
- X {"november", 10, 0, TM_MON},
- X {"december", 11, 0, TM_MON},
- X
- X {"sunday", 0, 0, TM_WDAY},
- X {"monday", 1, 0, TM_WDAY},
- X {"tuesday", 2, 0, TM_WDAY},
- X {"wednesday", 3, 0, TM_WDAY},
- X {"thursday", 4, 0, TM_WDAY},
- X {"friday", 5, 0, TM_WDAY},
- X {"saturday", 6, 0, TM_WDAY},
- X
- X {"gmt", 0*60, TWTIME, TM_ZON}, /* Greenwich */
- X {"gst", 0*60, TWTIME, TM_ZON},
- X {"gdt", 0*60, TWTIME+TWDST, TM_ZON}, /* ?? */
- X
- X {"ast", 4*60, TWTIME, TM_ZON}, /* Atlantic */
- X {"est", 5*60, TWTIME, TM_ZON}, /* Eastern */
- X {"cst", 6*60, TWTIME, TM_ZON}, /* Central */
- X {"mst", 7*60, TWTIME, TM_ZON}, /* Mountain */
- X {"pst", 8*60, TWTIME, TM_ZON}, /* Pacific */
- X {"yst", 9*60, TWTIME, TM_ZON}, /* Yukon */
- X {"hst", 10*60, TWTIME, TM_ZON}, /* Hawaii */
- X {"bst", 11*60, TWTIME, TM_ZON}, /* Bering */
- X
- X {"adt", 4*60, TWTIME+TWDST, TM_ZON}, /* Atlantic */
- X {"edt", 5*60, TWTIME+TWDST, TM_ZON}, /* Eastern */
- X {"cdt", 6*60, TWTIME+TWDST, TM_ZON}, /* Central */
- X {"mdt", 7*60, TWTIME+TWDST, TM_ZON}, /* Mountain */
- X {"pdt", 8*60, TWTIME+TWDST, TM_ZON}, /* Pacific */
- X {"ydt", 9*60, TWTIME+TWDST, TM_ZON}, /* Yukon */
- X {"hdt", 10*60, TWTIME+TWDST, TM_ZON}, /* Hawaii */
- X {"bdt", 11*60, TWTIME+TWDST, TM_ZON}, /* Bering */
- X
- X {"daylight", 1, TWTIME+TWDST, TM_ZON}, /* Local Daylight */
- X {"standard", 1, TWTIME, TM_ZON}, /* Local Standard */
- X {"std", 1, TWTIME, TM_ZON}, /* " " */
- X
- X {"am", 1, TWTIME, TM_AMPM},
- X {"pm", 2, TWTIME, TM_AMPM},
- X {"noon", 12,TWTIME+TW1200, 0}, /* Special frobs */
- X {"midnight", 0, TWTIME+TW1200, 0},
- X {"at", (long)ptnoise, TWSPEC, 0}, /* Noise word */
- X
- X {0, 0, 0, 0}, /* Zero entry to terminate searches */
- X};
- X
- X#define TMWILD (-2) /* Value meaning item specified as wild-card */
- X /* (May use someday...) */
- X
- Xstruct token {
- X char *tcp; /* pointer to string */
- X int tcnt; /* # chars */
- X char tbrk; /* "break" char */
- X char tbrkl; /* last break char */
- X char tflg; /* 0 = alpha, 1 = numeric */
- X union { /* Resulting value; */
- X int tnum;/* either a #, or */
- X struct tmwent *ttmw;/* ptr to a tmwent. */
- X } tval;
- X};
- X
- Xpartime(astr, atm)
- Xchar *astr;
- Xstruct tm *atm;
- X{ register int *tp;
- X register struct tmwent *twp;
- X register int i;
- X struct token btoken, atoken;
- X char *cp, ch;
- X int ord, midnoon;
- X int (*aproc)();
- X
- X tp = (int *)atm;
- X zaptime(tp); /* Initialize the TM structure */
- X midnoon = TMNULL; /* and our own temp stuff */
- X btoken.tcnt = btoken.tbrkl = 0;
- X btoken.tcp = astr;
- X
- Xdomore:
- X if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken)) /* Get a token */
- X { if(btoken.tval.tnum) return(0); /* Read error? */
- X if(midnoon != TMNULL) /* EOF, wrap up */
- X return(pt12hack(tp, midnoon));
- X return(1); /* Win return! */
- X }
- X if(btoken.tflg == 0) /* Alpha? */
- X { twp = btoken.tval.ttmw; /* Yes, get ptr to entry */
- X if(twp->wflgs&TWSPEC) /* Special alpha crock */
- X { aproc = (int (*) ()) (twp->wval);
- X if(!(*aproc)(tp, twp, &btoken))
- X return(0); /* ERR: special word err */
- X goto domore;
- X }
- X if(twp->wflgs&TW1200)
- X if(ptstash(&midnoon,(int)twp->wval))
- X return(0); /* ERR: noon/midnite clash */
- X else goto domore;
- X if(ptstash(&tp[twp->wtype],(int)twp->wval))
- X return(0); /* ERR: val already set */
- X if(twp->wtype == TM_ZON) /* If was zone, hack DST */
- X if(ptstash(&tp[TM_ISDST],(twp->wflgs&TWDST)))
- X return(0); /* ERR: DST conflict */
- X goto domore;
- X }
- X
- X /* Token is number. Lots of hairy heuristics. */
- X if(btoken.tcnt >= 7) /* More than 6 digits in string? */
- X return(0); /* ERR: number too big */
- X if(btoken.tcnt == 6) /* 6 digits = HHMMSS. Needs special crock */
- X { /* since 6 digits are too big for integer! */
- X i = (btoken.tcp[0]-'0')*10 /* Gobble 1st 2 digits */
- X + btoken.tcp[1]-'0';
- X btoken.tcnt = 2; /* re-read last 4 chars */
- X goto coltime;
- X }
- X
- X i = btoken.tval.tnum; /* Value now known to be valid; get it. */
- X if( btoken.tcnt == 5 /* 5 digits = HMMSS */
- X || btoken.tcnt == 3) /* 3 digits = HMM */
- X { if(btoken.tcnt != 3)
- X if(ptstash(&tp[TM_SEC], i%100))
- X return(0); /* ERR: sec conflict */
- X else i /= 100;
- Xhhmm4: if(ptstash(&tp[TM_MIN], i%100))
- X return(0); /* ERR: min conflict */
- X i /= 100;
- Xhh2: if(ptstash(&tp[TM_HOUR], i))
- X return(0); /* ERR: hour conflict */
- X goto domore;
- X }
- X
- X if(btoken.tcnt == 4) /* 4 digits = YEAR or HHMM */
- X { if(tp[TM_YEAR] != TMNULL) goto hhmm4; /* Already got yr? */
- X if(tp[TM_HOUR] != TMNULL) goto year4; /* Already got hr? */
- X if((i%100) > 59) goto year4; /* MM >= 60? */
- X if(btoken.tbrk == ':') /* HHMM:SS ? */
- X if( ptstash(&tp[TM_HOUR],i/100)
- X || ptstash(&tp[TM_MIN], i%100))
- X return(0); /* ERR: hr/min clash */
- X else goto coltm2; /* Go handle SS */
- X if(btoken.tbrk != ',' && btoken.tbrk != '/'
- X && ptitoken(btoken.tcp+btoken.tcnt,&atoken) /* Peek */
- X && atoken.tflg == 0 /* alpha */
- X && (atoken.tval.ttmw->wflgs&TWTIME)) /* HHMM-ZON */
- X goto hhmm4;
- X if(btoken.tbrkl == '-' /* DD-Mon-YYYY */
- X || btoken.tbrkl == ',' /* Mon DD, YYYY */
- X || btoken.tbrkl == '/' /* MM/DD/YYYY */
- X || btoken.tbrkl == '.' /* DD.MM.YYYY */
- X || btoken.tbrk == '-' /* YYYY-MM-DD */
- X ) goto year4;
- X goto hhmm4; /* Give up, assume HHMM. */
- X }
- X
- X /* From this point on, assume tcnt == 1 or 2 */
- X /* 2 digits = YY, MM, DD, or HH (MM and SS caught at coltime) */
- X if(btoken.tbrk == ':') /* HH:MM[:SS] */
- X goto coltime; /* must be part of time. */
- X if(i > 31) goto yy2; /* If >= 32, only YY poss. */
- X
- X /* Check for numerical-format date */
- X for (cp = "/-."; ch = *cp++;)
- X { ord = (ch == '.' ? 0 : 1); /* n/m = D/M or M/D */
- X if(btoken.tbrk == ch) /* "NN-" */
- X { if(btoken.tbrkl != ch)
- X { if(ptitoken(btoken.tcp+btoken.tcnt,&atoken)
- X && atoken.tflg == 0
- X && atoken.tval.ttmw->wtype == TM_MON)
- X goto dd2;
- X if(ord)goto mm2; else goto dd2; /* "NN-" */
- X } /* "-NN-" */
- X if(tp[TM_DAY] == TMNULL
- X && tp[TM_YEAR] != TMNULL) /* If "YY-NN-" */
- X goto mm2; /* then always MM */
- X if(ord)goto dd2; else goto mm2;
- X }
- X if(btoken.tbrkl == ch /* "-NN" */
- X && tp[ord ? TM_MON : TM_DAY] != TMNULL)
- X if(tp[ord ? TM_DAY : TM_MON] == TMNULL) /* MM/DD */
- X if(ord)goto dd2; else goto mm2;
- X else goto yy2; /* "-YY" */
- X }
- X
- X /* At this point only YY, DD, and HH are left.
- X * YY is very unlikely since value is <= 32 and there was
- X * no numerical format date. Make one last try at YY
- X * before dropping through to DD vs HH code.
- X */
- X if(btoken.tcnt == 2 /* If 2 digits */
- X && tp[TM_HOUR] != TMNULL /* and already have hour */
- X && tp[TM_DAY] != TMNULL /* and day, but */
- X && tp[TM_YEAR] == TMNULL) /* no year, then assume */
- X goto yy2; /* that's what we have. */
- X
- X /* Now reduced to choice between HH and DD */
- X if(tp[TM_HOUR] != TMNULL) goto dd2; /* Have hour? Assume day. */
- X if(tp[TM_DAY] != TMNULL) goto hh2; /* Have day? Assume hour. */
- X if(i > 24) goto dd2; /* Impossible HH means DD */
- X if(!ptitoken(btoken.tcp+btoken.tcnt, &atoken)) /* Read ahead! */
- X if(atoken.tval.tnum) return(0); /* ERR: bad token */
- X else goto dd2; /* EOF, assume day. */
- X if( atoken.tflg == 0 /* If next token is an alpha */
- X && atoken.tval.ttmw->wflgs&TWTIME) /* time-spec, assume hour */
- X goto hh2; /* e.g. "3 PM", "11-EDT" */
- X
- Xdd2: if(ptstash(&tp[TM_DAY],i)) /* Store day (1 based) */
- X return(0);
- X goto domore;
- X
- Xmm2: if(ptstash(&tp[TM_MON], i-1)) /* Store month (make zero based) */
- X return(0);
- X goto domore;
- X
- Xyy2: i += 1900;
- Xyear4: if(ptstash(&tp[TM_YEAR],i)) /* Store year (full number) */
- X return(0); /* ERR: year conflict */
- X goto domore;
- X
- X /* Hack HH:MM[[:]SS] */
- Xcoltime:
- X if(ptstash(&tp[TM_HOUR],i)) return(0);
- X if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))
- X return(!btoken.tval.tnum);
- X if(!btoken.tflg) return(0); /* ERR: HH:<alpha> */
- X if(btoken.tcnt == 4) /* MMSS */
- X if(ptstash(&tp[TM_MIN],btoken.tval.tnum/100)
- X || ptstash(&tp[TM_SEC],btoken.tval.tnum%100))
- X return(0);
- X else goto domore;
- X if(btoken.tcnt != 2
- X || ptstash(&tp[TM_MIN],btoken.tval.tnum))
- X return(0); /* ERR: MM bad */
- X if(btoken.tbrk != ':') goto domore; /* Seconds follow? */
- Xcoltm2: if(!ptitoken(btoken.tcp+btoken.tcnt,&btoken))
- X return(!btoken.tval.tnum);
- X if(!btoken.tflg || btoken.tcnt != 2 /* Verify SS */
- X || ptstash(&tp[TM_SEC], btoken.tval.tnum))
- X return(0); /* ERR: SS bad */
- X goto domore;
- X}
- X
- X/* Store date/time value, return 0 if successful.
- X * Fails if entry already set to a different value.
- X */
- Xptstash(adr,val)
- Xint *adr;
- X{ register int *a;
- X if( *(a=adr) != TMNULL)
- X return(*a != val);
- X *a = val;
- X return(0);
- X}
- X
- X/* This subroutine is invoked for NOON or MIDNIGHT when wrapping up
- X * just prior to returning from partime.
- X */
- Xpt12hack(atp, aval)
- Xint *atp, aval;
- X{ register int *tp, i, h;
- X tp = atp;
- X if (((i=tp[TM_MIN]) && i != TMNULL) /* Ensure mins, secs */
- X || ((i=tp[TM_SEC]) && i != TMNULL)) /* are 0 or unspec'd */
- X return(0); /* ERR: MM:SS not 00:00 */
- X i = aval; /* Get 0 or 12 (midnite or noon) */
- X if ((h = tp[TM_HOUR]) == TMNULL /* If hour unspec'd, win */
- X || h == 12) /* or if 12:00 (matches either) */
- X tp[TM_HOUR] = i; /* Then set time */
- X else if(!(i == 0 /* Nope, but if midnight and */
- X &&(h == 0 || h == 24))) /* time matches, can pass. */
- X return(0); /* ERR: HH conflicts */
- X tp[TM_AMPM] = TMNULL; /* Always reset this value if won */
- X return(1);
- X}
- X
- X/* Null routine for no-op tokens */
- X
- Xptnoise() { return(1); }
- X
- X/* Get a token and identify it to some degree.
- X * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise
- X * hit error of some sort
- X */
- X
- Xptitoken(astr, tkp)
- Xregister struct token *tkp;
- Xchar *astr;
- X{
- X register char *cp;
- X register int i;
- X
- X tkp->tval.tnum = 0;
- X if(pttoken(astr,tkp) == 0)
- X#ifdef DEBUG
- X {
- X VOID printf("EOF\n");
- X return(0);
- X }
- X#else
- X return(0);
- X#endif
- X cp = tkp->tcp;
- X
- X#ifdef DEBUG
- X i = cp[tkp->tcnt];
- X cp[tkp->tcnt] = 0;
- X VOID printf("Token: \"%s\" ",cp);
- X cp[tkp->tcnt] = i;
- X#endif
- X
- X if(tkp->tflg)
- X for(i = tkp->tcnt; i > 0; i--)
- X tkp->tval.tnum = (int)tkp->tval.tnum*10 + ((*cp++)-'0');
- X else
- X { i = ptmatchstr(cp, tkp->tcnt, tmwords);
- X tkp->tval.tnum = i ? i : -1; /* Set -1 for error */
- X
- X#ifdef DEBUG
- X if(!i) VOID printf("Not found!\n");
- X#endif
- X
- X if(!i) return(0);
- X }
- X
- X#ifdef DEBUG
- X if(tkp->tflg)
- X VOID printf("Val: %d.\n",tkp->tval.tnum);
- X else VOID printf("Found: \"%s\", val: %d., type %d\n",
- X tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);
- X#endif
- X
- X return(1);
- X}
- X
- X/* Read token from input string into token structure */
- Xpttoken(astr,tkp)
- Xregister struct token *tkp;
- Xchar *astr;
- X{
- X register char *cp;
- X register int c;
- X
- X tkp->tcp = cp = astr;
- X tkp->tbrkl = tkp->tbrk; /* Set "last break" */
- X tkp->tcnt = tkp->tbrk = tkp->tflg = 0;
- X
- X while(c = *cp++)
- X { switch(c)
- X { case ' ': case '\t': /* Flush all whitespace */
- X while((c = *cp++) && isspace(c));
- X cp--; /* Drop thru to handle brk */
- X case '(': case ')': /* Perhaps any non-alphanum */
- X case '-': case ',': /* shd qualify as break? */
- X case '/': case ':': case '.': /* Break chars */
- X if(tkp->tcnt == 0) /* If no token yet */
- X { tkp->tcp = cp; /* ignore the brk */
- X tkp->tbrkl = c;
- X continue; /* and go on. */
- X }
- X tkp->tbrk = c;
- X return(tkp->tcnt);
- X }
- X if(tkp->tcnt == 0) /* If first char of token, */
- X tkp->tflg = isdigit(c); /* determine type */
- X if(( isdigit(c) && tkp->tflg) /* If not first, make sure */
- X ||(!isdigit(c) && !tkp->tflg)) /* char matches type */
- X tkp->tcnt++; /* Win, add to token. */
- X else {
- X cp--; /* Wrong type, back up */
- X tkp->tbrk = c;
- X return(tkp->tcnt);
- X }
- X }
- X return(tkp->tcnt); /* When hit EOF */
- X}
- X
- X
- Xptmatchstr(astr,cnt,astruc)
- Xchar *astr;
- Xint cnt;
- Xstruct tmwent *astruc;
- X{ register char *cp, *mp;
- X register int c;
- X struct tmwent *lastptr;
- X struct integ { int word; }; /* For getting at array ptr */
- X int i;
- X
- X lastptr = 0;
- X for(;mp = (char *)((struct integ *)astruc)->word; astruc += 1)
- X { cp = astr;
- X for(i = cnt; i > 0; i--)
- X { switch((c = *cp++) ^ *mp++) /* XOR the chars */
- X { case 0: continue; /* Exact match */
- X case 040: if(isalpha(c))
- X continue;
- X }
- X break;
- X }
- X if(i==0)
- X if(*mp == 0) return((unsigned int)astruc); /* Exact match */
- X else if(lastptr) return(0); /* Ambiguous */
- X else lastptr = astruc; /* 1st ambig */
- X }
- X return((unsigned int)lastptr);
- X}
- X
- X
- X
- Xzaptime(tp)
- Xregister int *tp;
- X/* clears tm structure pointed to by tp */
- X{ register int i;
- X i = (sizeof (struct tm))/(sizeof (int));
- X do *tp++ = TMNULL; /* Set entry to "unspecified" */
- X while(--i); /* Faster than FOR */
- X}
- X@
- X
- X
- X1.4.2.1
- Xlog
- X@Start of Amiga RCS port branch.
- X@
- Xtext
- X@d31 1
- Xa31 5
- X<<<<<<< partime.c
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/partime.c,v 1.4.1.1 89/08/11 01:41:57 rsbx Exp Locker: rsbx $";
- X=======
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/partime.c,v 1.2 89/09/17 13:34:54 rick Exp $";
- X>>>>>>> 1.2
- Xa34 11
- X<<<<<<< partime.c
- X * Revision 1.4.1.1 89/08/11 01:41:57 rsbx
- X * Start of cbmvax RCS source branch.
- X=======
- X * Revision 1.2 89/09/17 13:34:54 rick
- X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
- X * All changes done with conditional compile (#ifdef AMIGA). This version
- X * compiles correctly with Lattice C version 5.02 or later.
- X>>>>>>> 1.2
- X *
- X<<<<<<< partime.c
- Xa35 3
- X * checked in with -k by rsbx at 89.08.10.16.06.05.
- X *
- X * Revision 1.4 89/05/01 14:48:46 narten
- Xa43 8
- X=======
- X * Revision 1.3 89/09/16 09:42:36 rick
- X * Modified AMIGA changes to work with Lattice C
- X *
- X * Revision 1.2 88/09/03 15:08:16 rick
- X * Port to AmigaDos. All done with conditional compiles
- X *
- X>>>>>>> 1.2
- Xa58 1
- X#ifndef AMIGA
- Xa61 1
- X#endif
- Xd76 1
- Xa76 1
- Xlong ptnoise();
- Xd129 1
- Xa129 1
- X {"at", 1, 0, 0}, /* Noise word */
- Xd152 1
- Xa152 2
- X{
- X register int *tp;
- Xa332 3
- X#ifdef AMIGA
- Xshort *adr;
- X#else
- Xd334 1
- Xa334 7
- X#endif
- X{
- X#ifdef AMIGA
- X register short *a;
- X#else
- X register int *a;
- X#endif
- Xa344 3
- X#ifdef AMIGA
- Xshort *atp, aval;
- X#else
- Xd346 1
- Xa346 7
- X#endif
- X{
- X#ifdef AMIGA
- X register short *tp, i, h;
- X#else
- X register int *tp, i, h;
- X#endif
- Xd364 1
- Xa364 1
- Xlong ptnoise() { return(1); }
- Xa379 1
- X<<<<<<< partime.c
- Xa382 5
- X=======
- X#ifdef MYDEBUG
- X VOID printf("EOF\n");
- X#endif MYDEBUG
- X>>>>>>> 1.2
- Xd390 1
- Xa390 1
- X#ifdef MYDEBUG
- Xa394 1
- X<<<<<<< partime.c
- Xa395 3
- X=======
- X#endif MYDEBUG
- X>>>>>>> 1.2
- Xd404 1
- Xa404 1
- X#ifdef MYDEBUG
- Xa405 1
- X<<<<<<< partime.c
- Xa406 3
- X=======
- X#endif MYDEBUG
- X>>>>>>> 1.2
- Xd411 1
- Xa411 1
- X#ifdef MYDEBUG
- Xa415 1
- X<<<<<<< partime.c
- Xa416 3
- X=======
- X#endif MYDEBUG
- X>>>>>>> 1.2
- Xa495 3
- X#ifdef AMIGA
- Xregister short *tp;
- X#else
- Xa496 1
- X#endif
- Xa498 3
- X#ifdef AMIGA
- X i = (sizeof (struct tm))/(sizeof (short));
- X#else
- Xa499 1
- X#endif
- X@
- X
- X
- X1.4.2.2
- Xlog
- X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
- Xsources I have here (and are later than the ones Rick used).
- X@
- Xtext
- X@d31 5
- Xa35 1
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/partime.c,v 1.4.2.1 89/10/13 19:17:41 rsbx Exp Locker: rsbx $";
- Xd39 1
- Xa39 3
- X * Revision 1.4.2.1 89/10/13 19:17:41 rsbx
- X * Start of Amiga RCS port branch.
- X *
- Xd42 6
- Xd49 1
- Xd62 8
- Xd427 2
- Xa428 1
- X#ifdef MYDEBUG
- Xd431 5
- Xd448 1
- Xd450 3
- Xd463 1
- Xd465 3
- Xd477 1
- Xd479 3
- Xd520 1
- X@
- X
- X
- X1.4.2.3
- Xlog
- X@Changed $Header$ to $Id$.
- X@
- Xtext
- X@d31 1
- Xa31 1
- X"$Id$";
- Xa34 4
- X * Revision 1.4.2.2 89/10/15 15:43:31 rsbx
- X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
- X * sources I have here (and are later than the ones Rick used).
- X *
- X@
- X
- X
- X1.4.1.1
- Xlog
- X@Start of cbmvax RCS source branch.
- X@
- Xtext
- X@d31 1
- Xa31 1
- X"$Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/partime.c,v 1.4 89/05/01 14:48:46 narten Exp $";
- Xa34 3
- X * Revision 1.4 89/05/01 14:48:46 narten
- X * checked in with -k by rsbx at 89.08.10.16.06.05.
- X *
- X@
- SHAR_EOF
- echo "extracting rcs/rcs.rcsfiles/rcs.c,v"
- sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcs.c,v
- Xhead 4.11;
- Xbranch 4.11.2;
- Xaccess ;
- Xsymbols amiga_rcs:4.11.2 cbmvax_source:4.11.1 uunet_june89_dist:4.11;
- Xlocks ; strict;
- Xcomment @ * @;
- X
- X
- X4.11
- Xdate 89.05.01.15.12.06; author narten; state Exp;
- Xbranches 4.11.1.1 4.11.2.1;
- Xnext ;
- X
- X4.11.1.1
- Xdate 89.08.11.01.42.01; author rsbx; state Exp;
- Xbranches ;
- Xnext ;
- X
- X4.11.2.1
- Xdate 89.10.13.19.17.47; author rsbx; state Exp;
- Xbranches ;
- Xnext 4.11.2.2;
- X
- X4.11.2.2
- Xdate 89.10.15.15.43.36; author rsbx; state Exp;
- Xbranches ;
- Xnext 4.11.2.3;
- X
- X4.11.2.3
- Xdate 89.10.16.19.06.13; author rsbx; state Exp;
- Xbranches ;
- Xnext 4.11.2.4;
- X
- X4.11.2.4
- Xdate 89.10.17.13.17.35; author rsbx; state Exp;
- Xbranches ;
- Xnext 4.11.2.5;
- X
- X4.11.2.5
- Xdate 89.10.30.13.38.35; author rsbx; state Exp;
- Xbranches ;
- Xnext 4.11.2.6;
- X
- X4.11.2.6
- Xdate 89.11.01.14.42.32; author rsbx; state Exp;
- Xbranches ;
- Xnext 4.11.2.7;
- X
- X4.11.2.7
- Xdate 89.11.05.23.14.17; author rsbx; state Exp;
- Xbranches ;
- Xnext 4.11.2.8;
- X
- X4.11.2.8
- Xdate 89.11.12.15.07.03; author rsbx; state Exp;
- Xbranches ;
- Xnext ;
- X
- X
- Xdesc
- X@RCS create/change operation.
- X@
- X
- X
- X
- X4.11
- Xlog
- X@checked in with -k by rsbx at 89.08.10.16.06.26.
- X@
- Xtext
- X@/*
- X * RCS create/change operation
- X */
- X#ifndef lint
- Xstatic char rcsid[]=
- X"$Header: /usr/src/local/bin/rcs/src/RCS/rcs.c,v 4.11 89/05/01 15:12:06 narten Exp $ Purdue CS";
- X#endif
- X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by Walter Tichy.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * Report all problems and direct all questions to:
- X * rcs-bugs@@cs.purdue.edu
- X *
- X
- X
- X
- X
- X
- X
- X
- X*/
- X
- X
- X
- X
- X/* $Log: rcs.c,v $
- X * Revision 4.11 89/05/01 15:12:06 narten
- X * changed copyright header to reflect current distribution rules
- X *
- X * Revision 4.10 88/11/08 16:01:54 narten
- X * didn't install previous patch correctly
- X *
- X * Revision 4.9 88/11/08 13:56:01 narten
- X * removed include <sysexits.h> (not needed)
- X * minor fix for -A option
- X *
- X * Revision 4.8 88/11/08 12:01:58 narten
- X * changes from eggert@@sm.unisys.com (Paul Eggert)
- X *
- X * Revision 4.8 88/08/09 19:12:27 eggert
- X * Don't access freed storage.
- X * Use execv(), not system(); yield proper exit status; remove lint.
- X *
- X * Revision 4.7 87/12/18 11:37:17 narten
- X * lint cleanups (Guy Harris)
- X *
- X * Revision 4.6 87/10/18 10:28:48 narten
- X * Updating verison numbers. Changes relative to 1.1 are actually
- X * relative to 4.3
- X *
- X * Revision 1.4 87/09/24 13:58:52 narten
- X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
- X * warnings)
- X *
- X * Revision 1.3 87/03/27 14:21:55 jenkins
- X * Port to suns
- X *
- X * Revision 1.2 85/12/17 13:59:09 albitz
- X * Changed setstate to rcs_setstate because of conflict with random.o.
- X *
- X * Revision 1.1 84/01/23 14:50:09 kcs
- X * Initial revision
- X *
- X * Revision 4.3 83/12/15 12:27:33 wft
- X * rcs -u now breaks most recent lock if it can't find a lock by the caller.
- X *
- X * Revision 4.2 83/12/05 10:18:20 wft
- X * Added conditional compilation for sending mail.
- X * Alternatives: V4_2BSD, V6, USG, and other.
- X *
- X * Revision 4.1 83/05/10 16:43:02 wft
- X * Simplified breaklock(); added calls to findlock() and getcaller().
- X * Added option -b (default branch). Updated -s and -w for -b.
- X * Removed calls to stat(); now done by pairfilenames().
- X * Replaced most catchints() calls with restoreints().
- X * Removed check for exit status of delivermail().
- X * Directed all interactive output to stderr.
- X *
- X * Revision 3.9.1.1 83/12/02 22:08:51 wft
- X * Added conditional compilation for 4.2 sendmail and 4.1 delivermail.
- X *
- X * Revision 3.9 83/02/15 15:38:39 wft
- X * Added call to fastcopy() to copy remainder of RCS file.
- X *
- X * Revision 3.8 83/01/18 17:37:51 wft
- X * Changed sendmail(): now uses delivermail, and asks whether to break the lock.
- X *
- X * Revision 3.7 83/01/15 18:04:25 wft
- X * Removed putree(); replaced with puttree() in rcssyn.c.
- X * Combined putdellog() and scanlogtext(); deleted putdellog().
- X * Cleaned up diagnostics and error messages. Fixed problem with
- X * mutilated files in case of deletions in 2 files in a single command.
- X * Changed marking of selector from 'D' to DELETE.
- X *
- X * Revision 3.6 83/01/14 15:37:31 wft
- X * Added ignoring of interrupts while new RCS file is renamed;
- X * Avoids deletion of RCS files by interrupts.
- X *
- X * Revision 3.5 82/12/10 21:11:39 wft
- X * Removed unused variables, fixed checking of return code from diff,
- X * introduced variant COMPAT2 for skipping Suffix on -A files.
- X *
- X * Revision 3.4 82/12/04 13:18:20 wft
- X * Replaced getdelta() with gettree(), changed breaklock to update
- X * field lockedby, added some diagnostics.
- X *
- X * Revision 3.3 82/12/03 17:08:04 wft
- X * Replaced getlogin() with getpwuid(), flcose() with ffclose(),
- X * /usr/ucb/Mail with macro MAIL. Removed handling of Suffix (-x).
- X * fixed -u for missing revno. Disambiguated structure members.
- X *
- X * Revision 3.2 82/10/18 21:05:07 wft
- X * rcs -i now generates a file mode given by the umask minus write permission;
- X * otherwise, rcs keeps the mode, but removes write permission.
- X * I added a check for write error, fixed call to getlogin(), replaced
- X * curdir() with getfullRCSname(), cleaned up handling -U/L, and changed
- X * conflicting, long identifiers.
- X *
- X * Revision 3.1 82/10/13 16:11:07 wft
- X * fixed type of variables receiving from getc() (char -> int).
- X */
- X
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "rcsbase.h"
- X#ifndef lint
- Xstatic char rcsbaseid[] = RCSBASE;
- X#endif
- X
- Xextern FILE * fopen();
- Xextern char * bindex();
- Xextern int expandsym(); /* get numeric revision name */
- Xextern struct hshentry * getnum();
- Xextern struct lock * addlock(); /* add a lock */
- Xextern char * getid();
- Xextern char Klog[], Khead[], Kaccess[], Kbranch[], Ktext[];
- X#ifdef COMPAT2
- Xextern char Ksuffix[];
- X#endif
- Xextern char * getcaller(); /* get login of caller */
- Xextern struct hshentry * findlock(); /* find and remove lock */
- Xextern struct hshentry * genrevs();
- Xextern char * checkid(); /* check an identifier */
- Xextern char * getfullRCSname(); /* get full path name of RCS file */
- Xextern char * mktempfile(); /* temporary file name generator */
- Xextern free();
- Xextern void catchints();
- Xextern void ignoreints();
- Xextern int nerror; /* counter for errors */
- Xextern int quietflag; /* diagnoses suppressed if true */
- Xextern char curlogmsg[]; /* current log message */
- Xextern char * resultfile; /* filename for fcopy */
- Xextern FILE *fcopy; /* result file during editing */
- Xextern FILE * finptr; /* RCS input file */
- Xextern FILE * frewrite; /* new RCS file */
- Xextern int rewriteflag; /* indicates whether input should be*/
- X /* echoed to frewrite */
- X
- Xchar * newRCSfilename, * diffilename, * cutfilename;
- Xchar * RCSfilename, * workfilename;
- Xextern struct stat RCSstat, workstat; /* file status of RCS and work file */
- Xextern int haveRCSstat, haveworkstat;/* status indicators */
- X
- Xchar accessorlst[strtsize];
- XFILE * fcut; /* temporary file to rebuild delta tree */
- Xint oldumask; /* save umask */
- X
- Xint initflag, strictlock, strict_selected, textflag;
- Xchar * textfile, * accessfile;
- Xchar * caller, numrev[30]; /* caller's login; */
- Xstruct access * newaccessor, * rmvaccessor, * rplaccessor;
- Xstruct access *curaccess, *rmaccess;
- Xstruct hshentry * gendeltas[hshsize];
- X
- Xstruct Lockrev {
- X char * revno;
- X struct Lockrev * nextrev;
- X};
- X
- Xstruct Symrev {
- X char * revno;
- X char * ssymbol;
- X int override;
- X struct Symrev * nextsym;
- X};
- X
- Xstruct Status {
- X char * revno;
- X char * status;
- X struct Status * nextstatus;
- X};
- X
- Xstruct delrevpair {
- X char * strt;
- X char * end;
- X int code;
- X};
- X
- Xstruct Lockrev * newlocklst, * rmvlocklst;
- Xstruct Symrev * assoclst, * lastassoc;
- Xstruct Status * statelst, * laststate;
- Xstruct delrevpair * delrev;
- Xstruct hshentry * cuthead, *cuttail, * delstrt;
- Xchar branchnum[revlength], * branchsym;
- Xstruct hshentry branchdummy;
- Xchar * commsyml;
- Xchar * headstate;
- Xint lockhead,unlockcaller,chgheadstate,branchflag,commentflag;
- Xint delaccessflag;
- Xenum stringwork {copy, edit, empty}; /* expand and edit_expand not needed */
- X
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar * argv[];
- X{
- X char *comdusge;
- X int result;
- X struct access *removeaccess(), * getaccessor();
- X struct Lockrev *rmnewlocklst();
- X struct Lockrev *curlock, * rmvlock, *lockpt;
- X struct Status * curstate;
- X struct access *temp, *temptr;
- X int status;
- X
- X status = 0;
- X nerror = 0;
- X catchints();
- X cmdid = "rcs";
- X quietflag = false;
- X comdusge ="command format:\nrcs -i -alogins -Alogins -e[logins] -b[rev] -c[commentleader] -l[rev] -u[rev] -L -U -nname[:rev] -Nname[:rev] -orange -sstate[:rev] -t[textfile] file....";
- X rplaccessor = nil; delstrt = nil;
- X accessfile = textfile = caller = nil;
- X branchflag = commentflag = chgheadstate = false;
- X lockhead = false; unlockcaller=false;
- X initflag= textflag = false;
- X strict_selected = 0;
- X
- X caller=getcaller();
- X laststate = statelst = nil;
- X lastassoc = assoclst = nil;
- X curlock = rmvlock = newlocklst = rmvlocklst = nil;
- X curaccess = rmaccess = rmvaccessor = newaccessor = nil;
- X delaccessflag = false;
- X
- X /* preprocessing command options */
- X while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
- X switch ((*argv)[1]) {
- X
- X case 'i': /* initail version */
- X initflag = true;
- X break;
- X
- X case 'b': /* change default branch */
- X if (branchflag)warn("Redfinition of option -b");
- X branchflag= true;
- X branchsym = (*argv)+2;
- X break;
- X
- X case 'c': /* change comment symbol */
- X if (commentflag)warn("Redefinition of option -c");
- X commentflag = true;
- X commsyml = (*argv)+2;
- X break;
- X
- X case 'a': /* add new accessor */
- X if ( (*argv)[2] == '\0') {
- X error("Login name missing after -a");
- X }
- X if ( (temp = getaccessor((*argv)+1)) ) {
- X if ( newaccessor )
- X curaccess->nextaccess = temp->nextaccess;
- X else
- X newaccessor = temp->nextaccess;
- X temp->nextaccess = nil;
- X curaccess = temp;
- X }
- X break;
- X
- X case 'A': /* append access list according to accessfile */
- X if ( (*argv)[2] == '\0') {
- X error("Missing file name after -A");
- X break;
- X }
- X if ( accessfile) warn("Redefinition of option -A");
- X *argv = *argv+2;
- X if( pairfilenames(1, argv, true, false) > 0) {
- X releaselst(newaccessor);
- X newaccessor = curaccess = nil;
- X releaselst(rmvaccessor);
- X rmvaccessor = rmaccess = nil;
- X accessfile = RCSfilename;
- X }
- X else
- X accessfile = nil;
- X break;
- X
- X case 'e': /* remove accessors */
- X if ( (*argv)[2] == '\0' ) {
- X delaccessflag = true;
- X break;
- X }
- X if ( (temp = getaccessor((*argv)+1)) ) {
- X if ( rmvaccessor )
- X rmaccess->nextaccess = temp->nextaccess;
- X else
- X rmvaccessor = temp->nextaccess;
- X temptr = temp->nextaccess;
- X temp->nextaccess = nil;
- X rmaccess = temp;
- X while( temptr ) {
- X newaccessor = removeaccess(temptr,newaccessor,false);
- X temptr = temptr->nextaccess;
- X }
- X curaccess = temp = newaccessor;
- X while( temp){
- X curaccess = temp;
- X temp = temp->nextaccess;
- X }
- X }
- X break;
- X
- X case 'l': /* lock a revision if it is unlocked */
- X if ( (*argv)[2] == '\0'){ /* lock head or def. branch */
- X lockhead = true;
- X break;
- X }
- X lockpt = (struct Lockrev *)talloc(sizeof(struct Lockrev));
- X lockpt->revno = (*argv)+2;
- X lockpt->nextrev = nil;
- X if ( curlock )
- X curlock->nextrev = lockpt;
- X else
- X newlocklst = lockpt;
- X curlock = lockpt;
- X break;
- X
- X case 'u': /* release lock of a locked revision */
- X if ( (*argv)[2] == '\0'){ /* unlock head */
- X unlockcaller=true;
- X break;
- X }
- X lockpt = (struct Lockrev *)talloc(sizeof(struct Lockrev));
- X lockpt->revno = (*argv)+2;
- X lockpt->nextrev = nil;
- X if (rmvlock)
- X rmvlock->nextrev = lockpt;
- X else
- X rmvlocklst = lockpt;
- X rmvlock = lockpt;
- X
- X curlock = rmnewlocklst(lockpt);
- X break;
- X
- X case 'L': /* set strict locking */
- X if (strict_selected++) { /* Already selected L or U? */
- X if (!strictlock) /* Already selected -U? */
- X warn("Option -L overrides -U");
- X }
- X strictlock = true;
- X break;
- X
- X case 'U': /* release strict locking */
- X if (strict_selected++) { /* Already selected L or U? */
- X if (strictlock) /* Already selected -L? */
- X warn("Option -L overrides -U");
- X }
- X else
- X strictlock = false;
- X break;
- X
- X case 'n': /* add new association: error, if name exists */
- X if ( (*argv)[2] == '\0') {
- X error("Missing symbolic name after -n");
- X break;
- X }
- X getassoclst(false, (*argv)+1);
- X break;
- X
- X case 'N': /* add or change association */
- X if ( (*argv)[2] == '\0') {
- X error("Missing symbolic name after -N");
- X break;
- X }
- X getassoclst(true, (*argv)+1);
- X break;
- X
- X case 'o': /* delete revisins */
- X if (delrev) warn("Redefinition of option -o");
- X if ( (*argv)[2] == '\0' ) {
- X error("Missing revision range after -o");
- X break;
- X }
- X getdelrev( (*argv)+1 );
- X break;
- X
- X case 's': /* change state attribute of a revision */
- X if ( (*argv)[2] == '\0') {
- X error("State missing after -s");
- X break;
- X }
- X getstates( (*argv)+1);
- X break;
- X
- X case 't': /* change descriptive text */
- X textflag=true;
- X if ((*argv)[2]!='\0'){
- X if (textfile!=nil)warn("Redefinition of -t option");
- X textfile = (*argv)+2;
- X }
- X break;
- X
- X case 'q':
- X quietflag = true;
- X break;
- X default:
- X faterror("Unknown option: %s\n%s", *argv, comdusge);
- X };
- X } /* end processing of options */
- X
- X if (argc<1) faterror("No input file\n%s", comdusge);
- X if (nerror) { /* exit, if any error in command options */
- X diagnose("%s aborted",cmdid);
- X exit(1);
- X }
- X if (accessfile) /* get replacement for access list */
- X getrplaccess();
- X if (nerror) {
- X diagnose("%s aborted",cmdid);
- X exit(1);
- X }
- X
- X /* now handle all filenames */
- X do {
- X rewriteflag = false;
- X finptr=frewrite=NULL;
- X
- X if ( initflag ) {
- X switch( pairfilenames(argc, argv, false, false) ) {
- X case -1: break; /* not exist; ok */
- X case 0: continue; /* error */
- X case 1: error("file %s exists already", RCSfilename);
- X VOID fclose(finptr);
- X continue;
- X }
- X }
- X else {
- X switch( pairfilenames(argc, argv, true, false) ) {
- X case -1: continue; /* not exist */
- X case 0: continue; /* errors */
- X case 1: break; /* file exists; ok*/
- X }
- X }
- X
- X
- X /* now RCSfilename contains the name of the RCS file, and
- X * workfilename contains the name of the working file.
- X * if !initflag, finptr contains the file descriptor for the
- X * RCS file. The admin node is initialized.
- X */
- X
- X diagnose("RCS file: %s", RCSfilename);
- X
- X if (!trydiraccess(RCSfilename)) continue; /* give up */
- X if (!initflag && !checkaccesslist(caller)) continue; /* give up */
- X if (!trysema(RCSfilename,true)) continue; /* give up */
- X
- X gettree(); /* read in delta tree */
- X
- X /* update admin. node */
- X if (strict_selected) StrictLocks = strictlock;
- X if (commentflag) Comment = commsyml;
- X
- X /* update default branch */
- X if (branchflag && expandsym(branchsym, branchnum)) {
- X if (countnumflds(branchnum)>0) {
- X branchdummy.num=branchnum;
- X Dbranch = &branchdummy;
- X } else
- X Dbranch = nil;
- X }
- X
- X /* update access list */
- X if ( delaccessflag ) AccessList = nil;
- X if ( accessfile ) {
- X temp = rplaccessor;
- X while( temp ) {
- X temptr = temp->nextaccess;
- X if ( addnewaccess(temp) )
- X temp->nextaccess = nil;
- X temp = temptr;
- X }
- X }
- X temp = rmvaccessor;
- X while(temp) { /* remove accessors from accesslist */
- X AccessList = removeaccess(temp, AccessList,true);
- X temp = temp->nextaccess;
- X }
- X temp = newaccessor;
- X while( temp) { /* add new accessors */
- X temptr = temp->nextaccess;
- X if ( addnewaccess( temp ) )
- X temp->nextaccess = nil;
- X temp = temptr;
- X }
- X
- X updateassoc(); /* update association list */
- X
- X updatelocks(); /* update locks */
- X
- X /* update state attribution */
- X if (chgheadstate) {
- X /* change state of default branch or head */
- X if (Dbranch==nil) {
- X if (Head==nil)
- X warn("Can't change states in an empty tree");
- X else Head->state = headstate;
- X } else {
- X rcs_setstate(Dbranch->num,headstate); /* Can't set directly */
- X }
- X }
- X curstate = statelst;
- X while( curstate ) {
- X rcs_setstate(curstate->revno,curstate->status);
- X curstate = curstate->nextstatus;
- X }
- X
- X cuthead = cuttail = nil;
- X if ( delrev && removerevs()) {
- X /* rebuild delta tree if some deltas are deleted */
- X if ( cuttail )
- X VOID genrevs(cuttail->num, (char *)nil,(char *)nil,
- X (char *)nil, gendeltas);
- X buildtree();
- X }
- X
- X
- X /* prepare for rewriting the RCS file */
- X newRCSfilename=mktempfile(RCSfilename,NEWRCSFILE);
- X oldumask = umask(0222); /* turn off write bits */
- X if ((frewrite=fopen(newRCSfilename, "w"))==NULL) {
- X VOID fclose(finptr);
- X error("Can't open file %s",newRCSfilename);
- X continue;
- X }
- X VOID umask(oldumask);
- X putadmin(frewrite);
- X if ( Head )
- X puttree(Head, frewrite);
- X putdesc(initflag,textflag,textfile,quietflag);
- X rewriteflag = false;
- X
- X if ( Head) {
- X if (!delrev) {
- X /* no revision deleted */
- X fastcopy(finptr,frewrite);
- X } else {
- X if ( cuttail )
- X buildeltatext(gendeltas);
- X else
- X scanlogtext((struct hshentry *)nil,empty);
- X /* copy rest of delta text nodes that are not deleted */
- X }
- X }
- X ffclose(frewrite); frewrite = NULL;
- X if ( ! nerror ) { /* move temporary file to RCS file if no error */
- X ignoreints(); /* ignore interrupts */
- X if(rename(newRCSfilename,RCSfilename)<0) {
- X error("Can't create RCS file %s; saved in %s",
- X RCSfilename, newRCSfilename);
- X newRCSfilename[0] = '\0'; /* avoid deletion by cleanup */
- X restoreints();
- X VOID cleanup();
- X break;
- X }
- X newRCSfilename[0]='\0'; /* avoid re-unlinking by cleanup()*/
- X /* update mode */
- X result=0;
- X if (!initflag) /* preserve mode bits */
- X result=chmod(RCSfilename,RCSstat.st_mode & ~0222);
- X elsif (haveworkstat==0) /* initialization, and work file exists */
- X result=chmod(RCSfilename,workstat.st_mode & ~0222);
- X if (result<0) warn("Can't set mode of %s",RCSfilename);
- X
- X restoreints(); /* catch them all again */
- X diagnose("done");
- X } else {
- X diagnose("%s aborted; %s unchanged.",cmdid,RCSfilename);
- X status = 1;
- X nerror = 0;
- X }
- X } while (cleanup(),
- X ++argv, --argc >=1);
- X
- X exit(status);
- X} /* end of main (rcs) */
- X
- X
- X
- Xgetassoclst(flag, sp)
- Xint flag;
- Xchar * sp;
- X/* Function: associate a symbolic name to a revision or branch, */
- X/* and store in assoclst */
- X
- X{
- X struct Symrev * pt;
- X char * temp, *temp2;
- X int c;
- X
- X while( (c=(*++sp)) == ' ' || c == '\t' || c =='\n') ;
- X temp = sp;
- X temp2=checkid(sp, ':'); /* check for invalid symbolic name */
- X sp = temp2; c = *sp; *sp = '\0';
- X while( c == ' ' || c == '\t' || c == '\n') c = *++sp;
- X
- X if ( c != ':' && c != '\0') {
- X error("Invalid string %s after option -n or -N",sp);
- X return;
- X }
- X
- X pt = (struct Symrev *)talloc(sizeof(struct Symrev));
- X pt->ssymbol = temp;
- X pt->override = flag;
- X if (c == '\0') /* delete symbol */
- X pt->revno = nil;
- X else {
- X while( (c = *++sp) == ' ' || c == '\n' || c == '\t') ;
- X if ( c == '\0' )
- X pt->revno = nil;
- X else
- X pt->revno = sp;
- X }
- X pt->nextsym = nil;
- X if (lastassoc)
- X lastassoc->nextsym = pt;
- X else
- X assoclst = pt;
- X lastassoc = pt;
- X return;
- X}
- X
- X
- X
- Xstruct access * getaccessor( sp)
- Xchar *sp;
- X/* Function: get the accessor list of options -e and -a, */
- X/* and store in curpt */
- X
- X
- X{
- X struct access * curpt, * pt, *pre;
- X char *temp;
- X register c;
- X
- X while( ( c = *++sp) == ' ' || c == '\n' || c == '\t' || c == ',') ;
- X if ( c == '\0') {
- X error("Missing login name after option -a or -e");
- X return nil;
- X }
- X
- X curpt = pt = nil;
- X while( c != '\0') {
- X temp=checkid(sp,',');
- X pt = (struct access *)talloc(sizeof(struct access));
- X pt->login = sp;
- X if ( curpt )
- X pre->nextaccess = pt;
- X else
- X curpt = pt;
- X pt->nextaccess = curpt;
- X pre = pt;
- X sp = temp; c = *sp; *sp = '\0';
- X while( c == ' ' || c == '\n' || c == '\t'|| c == ',')c =(*++sp);
- X }
- X return pt;
- X}
- X
- X
- X
- Xgetstates(sp)
- Xchar *sp;
- X/* Function: get one state attribute and the corresponding */
- X/* revision and store in statelst */
- X
- X{
- X char *temp, *temp2;
- X struct Status *pt;
- X register c;
- X
- X while( (c=(*++sp)) ==' ' || c == '\t' || c == '\n') ;
- X temp = sp;
- X temp2=checkid(sp,':'); /* check for invalid state attribute */
- X sp = temp2; c = *sp; *sp = '\0';
- X while( c == ' ' || c == '\t' || c == '\n' ) c = *++sp;
- X
- X if ( c == '\0' ) { /* change state of def. branch or Head */
- X chgheadstate = true;
- X headstate = temp;
- X return;
- X }
- X else if ( c != ':' ) {
- X error("Missing ':' after state in option -s");
- X return;
- X }
- X
- X while( (c = *++sp) == ' ' || c == '\t' || c == '\n') ;
- X pt = (struct Status *)talloc(sizeof(struct Status));
- X pt->status = temp;
- X pt->revno = sp;
- X pt->nextstatus = nil;
- X if (laststate)
- X laststate->nextstatus = pt;
- X else
- X statelst = pt;
- X laststate = pt;
- X}
- X
- X
- X
- Xgetrplaccess()
- X/* Function : get the accesslist of the 'accessfile' */
- X/* and place in rplaccessor */
- X{
- X register char *id, *nextp;
- X struct access *newaccess, *oldaccess;
- X
- X if ( (finptr=fopen(accessfile, "r")) == NULL) {
- X faterror("Can't open file %s", accessfile);
- X }
- X Lexinit();
- X nextp = &accessorlst[0];
- X
- X if ( ! getkey(Khead)) faterror("Missing head in %s", accessfile);
- X VOID getnum();
- X if ( ! getlex(SEMI) ) serror("Missing ';' after head in %s",accessfile);
- X
- X if (getkey(Kbranch)) { /* optional */
- X Dbranch=getnum();
- X if (!getlex(SEMI)) serror("Missing ';' after branch list");
- X }
- X
- X
- X#ifdef COMPAT2
- X /* read suffix. Only in release 2 format */
- X if (getkey(Ksuffix)) {
- X if (nexttok==STRING) {
- X readstring(); nextlex(); /*through away the suffix*/
- X } elsif(nexttok==ID) {
- X nextlex();
- X }
- X if ( ! getlex(SEMI) ) serror("Missing ';' after suffix in %s",accessfile);
- X }
- X#endif
- X
- X if (! getkey(Kaccess))fatserror("Missing access list in %s",accessfile);
- X oldaccess = nil;
- X while( id =getid() ) {
- X newaccess = (struct access *)talloc(sizeof(struct access));
- X newaccess->login = nextp;
- X newaccess->nextaccess = nil;
- X while( ( *nextp++ = *id++) != '\0') ;
- X if ( oldaccess )
- X oldaccess->nextaccess = newaccess;
- X else
- X rplaccessor = newaccess;
- X oldaccess = newaccess;
- X }
- X if ( ! getlex(SEMI))serror("Missing ';' after access list in %s",accessfile);
- X return;
- X}
- X
- X
- X
- Xgetdelrev(sp)
- Xchar *sp;
- X/* Function: get revision range or branch to be deleted, */
- X/* and place in delrev */
- X{
- X int c;
- X struct delrevpair *pt;
- X
- X if (delrev) free((char *)delrev);
- X
- X pt = (struct delrevpair *)talloc(sizeof(struct delrevpair));
- X while((c = (*++sp)) == ' ' || c == '\n' || c == '\t') ;
- X
- X if ( c == '<' || c == '-' ) { /* -o -rev or <rev */
- X while( (c = (*++sp)) == ' ' || c == '\n' || c == '\t') ;
- X pt->strt = sp; pt->code = 1;
- X while( c != ' ' && c != '\n' && c != '\t' && c != '\0') c =(*++sp);
- X *sp = '\0';
- X pt->end = nil; delrev = pt;
- X return;
- X }
- X else {
- X pt->strt = sp;
- X while( c != ' ' && c != '\n' && c != '\t' && c != '\0'
- X && c != '-' && c != '<' ) c = *++sp;
- X *sp = '\0';
- X while( c == ' ' || c == '\n' || c == '\t' ) c = *++sp;
- X if ( c == '\0' ) { /* -o rev or branch */
- X pt->end = nil; pt->code = 0;
- X delrev = pt;
- X return;
- X }
- X if ( c != '-' && c != '<') {
- X faterror("Invalid range %s %s after -o", pt->strt, sp);
- X free((char *)pt);
- X return;
- X }
- X while( (c = *++sp) == ' ' || c == '\n' || c == '\t') ;
- X if ( c == '\0') { /* -o rev- or rev< */
- X pt->end = nil; pt->code = 2;
- X delrev = pt;
- X return;
- X }
- X }
- X /* -o rev1-rev2 or rev1<rev2 */
- X pt->end = sp; pt->code = 3; delrev = pt;
- X while( c!= ' ' && c != '\n' && c != '\t' && c != '\0') c = *++sp;
- X *sp = '\0';
- X}
- X
- X
- X
- X
- Xscanlogtext(delta,func)
- Xstruct hshentry * delta; enum stringwork func;
- X/* Function: Scans delta text nodes up to and including the one given
- X * by delta, or up to last one present, if delta==nil.
- X * For the one given by delta (if delta!=nil), the log message is saved into
- X * curlogmsg and the text is processed according to parameter func.
- X * Assumes the initial lexeme must be read in first.
- X * Does not advance nexttok after it is finished, except if delta==nil.
- X */
- X{ struct hshentry * nextdelta;
- X
- X do {
- X rewriteflag = false;
- X nextlex();
- X if (!(nextdelta=getnum())) {
- X if(delta)
- X faterror("Can't find delta for revision %s", delta->num);
- X else return; /* no more delta text nodes */
- X }
- X if ( nextdelta->selector != DELETE) {
- X rewriteflag = true;
- X VOID fprintf(frewrite,DELNUMFORM,nextdelta->num,Klog);
- X }
- X if (!getkey(Klog) || nexttok!=STRING)
- X serror("Missing log entry");
- X elsif (delta==nextdelta) {
- X VOID savestring(curlogmsg,logsize);
- X delta->log=curlogmsg;
- X } else {readstring();
- X if (delta!=nil) delta->log="";
- X }
- X nextlex();
- X if (!getkey(Ktext) || nexttok!=STRING)
- X fatserror("Missing delta text");
- X
- X if(delta==nextdelta)
- X /* got the one we're looking for */
- X switch (func) {
- X case copy: copystring();
- X break;
- X case edit: editstring((struct hshentry *)nil);
- X break;
- X default: faterror("Wrong scanlogtext");
- X }
- X else readstring(); /* skip over it */
- X
- X } while (delta!=nextdelta);
- X}
- X
- X
- X
- Xreleaselst(sourcelst)
- Xstruct access * sourcelst;
- X/* Function: release the storages whose address are in sourcelst */
- X
- X{
- X struct access * pt;
- X
- X pt = sourcelst;
- X while(pt) {
- X struct access *pn = pt->nextaccess;
- X free((char *)pt);
- X pt = pn;
- X }
- X}
- X
- X
- X
- Xstruct Lockrev * rmnewlocklst(which)
- Xstruct Lockrev * which;
- X/* Function: remove lock to revision which->revno from newlocklst */
- X
- X{
- X struct Lockrev * pt, *pre;
- X
- X while( newlocklst && (! strcmp(newlocklst->revno, which->revno))){
- X struct Lockrev *pn = newlocklst->nextrev;
- X free((char *)newlocklst);
- X newlocklst = pn;
- X }
- X
- X pt = pre = newlocklst;
- X while( pt ) {
- X if ( ! strcmp(pt->revno, which->revno) ) {
- X pre->nextrev = pt->nextrev;
- X free((char *)pt);
- X pt = pre->nextrev;
- X }
- X else {
- X pre = pt;
- X pt = pt->nextrev;
- X }
- X }
- X return pre;
- X}
- X
- X
- X
- Xstruct access * removeaccess( who, sourcelst,flag)
- Xstruct access * who, * sourcelst;
- Xint flag;
- X/* Function: remove the accessor-- who from sourcelst */
- X
- X{
- X struct access *pt, *pre;
- X
- X pt = sourcelst;
- X while( pt && (! strcmp(who->login, pt->login) )) {
- X pre = pt->nextaccess;
- X free((char *)pt);
- X pt = pre;
- X flag = false;
- X }
- X pre = sourcelst = pt;
- X while( pt ) {
- X if ( ! strcmp(who->login, pt->login) ) {
- X pre->nextaccess = pt->nextaccess;
- X free((char *)pt);
- X pt = pre->nextaccess;
- X flag = false;
- X }
- X else {
- X pre = pt;
- X pt = pt->nextaccess;
- X }
- X }
- X if ( flag ) warn("Can't remove a nonexisting accessor %s",who->login);
- X return sourcelst;
- X}
- X
- X
- X
- Xint addnewaccess( who )
- Xstruct access * who;
- X/* Function: add new accessor-- who into AccessList */
- X
- X{
- X struct access *pt, *pre;
- X
- X pre = pt = AccessList;
- X
- X while( pt ) {
- X if ( strcmp( who->login, pt->login) ) {
- X pre = pt;
- X pt = pt->nextaccess;
- X }
- X else
- X return 0;
- X }
- X if ( pre == pt )
- X AccessList = who;
- X else
- X pre->nextaccess = who;
- X return 1;
- X}
- X
- X
- Xsendmail(Delta, who)
- Xchar * Delta, *who;
- X/* Function: mail to who, informing him that his lock on delta was
- X * broken by caller. Ask first whether to go ahead. Return false on
- X * error or if user decides not to break the lock.
- X */
- X{
- X char * messagefile;
- X int old1, old2, c, response;
- X FILE * mailmess;
- X
- X
- X VOID fprintf(stderr, "Revision %s is already locked by %s.\n", Delta, who);
- X VOID fprintf(stderr, "Do you want to break the lock? [ny](n): ");
- X response=c=getchar();
- X while (!(c==EOF || c=='\n')) c=getchar();/*skip to end of line*/
- X if (response=='\n'||response=='n'||response=='N') return false;
- X
- X /* go ahead with breaking */
- X messagefile=mktempfile("/tmp/", "RCSmailXXXXXX");
- X if ( (mailmess = fopen(messagefile, "w")) == NULL) {
- X faterror("Can't open file %s", messagefile);
- X }
- X
- X VOID fprintf(mailmess, "Subject: Broken lock on %s\n\n",bindex(RCSfilename,'/'));
- X VOID fprintf(mailmess, "Your lock on revision %s of file %s\n",Delta, getfullRCSname());
- X VOID fprintf(mailmess,"has been broken by %s for the following reason:\n",caller);
- X VOID fputs("State the reason for breaking the lock:\n", stderr);
- X VOID fputs("(terminate with ^D or single '.')\n>> ", stderr);
- X
- X old1 = '\n'; old2 = ' ';
- X for (; ;) {
- X c = getchar();
- X if ( c == EOF ) {
- X VOID putc('\n',stderr);
- X VOID fprintf(mailmess, "%c\n", old1);
- X break;
- X }
- X else if ( c == '\n' && old1 == '.' && old2 == '\n')
- X break;
- X else {
- X VOID fputc( old1, mailmess);
- X old2 = old1; old1 = c;
- X if (c== '\n') VOID fputs(">> ", stderr);
- X }
- X }
- X ffclose(mailmess);
- X
- X /* ignore the exit status, even if delivermail unsuccessful */
- X VOID run(messagefile,(char*)nil,
- X#ifdef SENDMAIL
- X "/usr/lib/sendmail",
- X#else
- X# ifdef DELIVERMAIL
- X "/etc/delivermail","-w",
- X# else
- X "/bin/mail",
- X# endif
- X#endif
- X who,(char*)nil);
- X VOID unlink(messagefile);
- X return(true);
- X}
- X
- X
- X
- Xstatic breaklock(who,delta)
- Xchar * who; struct hshentry * delta;
- X/* function: Finds the lock held by who on delta,
- X * and removes it.
- X * Sends mail if a lock different from the caller's is broken.
- X * Prints an error message if there is no such lock or error.
- X */
- X{
- X register struct lock * next, * trail;
- X char * num;
- X struct lock dummy;
- X int whor, numr;
- X
- X num=delta->num;
- X dummy.nextlock=next=Locks;
- X trail = &dummy;
- X while (next!=nil) {
- X if (num != nil)
- X numr = strcmp(num, next->delta->num);
- X
- X whor=strcmp(who,next->login);
- X if (whor==0 && numr==0) break; /* exact match */
- X if (numr==0 && whor !=0) {
- X if (!sendmail( num, next->login)){
- X diagnose("%s still locked by %s",num,next->login);
- X return;
- X } else break; /* continue after loop */
- X }
- X trail=next;
- X next=next->nextlock;
- X }
- X if (next!=nil) {
- X /*found one */
- X diagnose("%s unlocked",next->delta->num);
- X trail->nextlock=next->nextlock;
- X next->delta->lockedby=nil;
- X Locks=dummy.nextlock;
- X } else {
- X error("no lock set on revision %s", num);
- X }
- X}
- X
- X
- X
- Xstruct hshentry *searchcutpt(object, length, store)
- Xchar * object;
- Xint length;
- Xstruct hshentry * * store;
- X/* Function: Search store and return entry with number being object. */
- X/* cuttail = nil, if the entry is Head; otherwise, cuttail */
- X/* is the entry point to the one with number being object */
- X
- X{
- X while( compartial( (*store++)->num, object, length) ) ;
- X store--;
- X
- X if ( *store == Head)
- X cuthead = nil;
- X else
- X cuthead = *(store -1);
- X return *store;
- X}
- X
- X
- X
- Xint branchpoint(strt, tail)
- Xstruct hshentry *strt, *tail;
- X/* Function: check whether the deltas between strt and tail */
- X/* are locked or branch point, return 1 if any is */
- X/* locked or branch point; otherwise, return 0 and */
- X/* mark DELETE on selector */
- X
- X{
- X struct hshentry *pt;
- X struct lock *lockpt;
- X int flag;
- X
- X
- X pt = strt;
- X flag = false;
- X while( pt != tail) {
- X if ( pt->branches ){ /* a branch point */
- X flag = true;
- X error("Can't remove branch point %s", pt->num);
- X }
- X lockpt = Locks;
- X while(lockpt && lockpt->delta != pt)
- X lockpt = lockpt->nextlock;
- X if ( lockpt ) {
- X flag = true;
- X error("Can't remove locked revision %s",pt->num);
- X }
- X pt = pt->next;
- X }
- X
- X if ( ! flag ) {
- X pt = strt;
- X while( pt != tail ) {
- X pt->selector = DELETE;
- X diagnose("deleting revision %s ",pt->num);
- X pt = pt->next;
- X }
- X }
- X return flag;
- X}
- X
- X
- X
- Xremoverevs()
- X/* Function: get the revision range to be removed, and place the */
- X/* first revision removed in delstrt, the revision before */
- X/* delstrt in cuthead( nil, if delstrt is head), and the */
- X/* revision after the last removed revision in cuttail(nil */
- X/* if the last is a leaf */
- X
- X{
- X struct hshentry *target, *target2, * temp, *searchcutpt();
- X int length, flag;
- X
- X flag = false;
- X if ( ! expandsym(delrev->strt, &numrev[0]) ) return 0;
- X target = genrevs(&numrev[0], (char *)nil, (char *)nil, (char *)nil, gendeltas);
- X if ( ! target ) return 0;
- X if ( cmpnum(target->num, &numrev[0]) ) flag = true;
- X length = countnumflds( &numrev[0] );
- X
- X if ( delrev->code == 0 ) { /* -o rev or -o branch */
- X if ( length % 2)
- X temp=searchcutpt(target->num,length+1,gendeltas);
- X else if (flag) {
- X error("Revision %s does not exist", &numrev[0]);
- X return 0;
- X }
- X else
- X temp = searchcutpt(&numrev[0],length,gendeltas);
- X cuttail = target->next;
- X if ( branchpoint(temp, cuttail) ) {
- X cuttail = nil;
- X return 0;
- X }
- X delstrt = temp; /* first revision to be removed */
- X return 1;
- X }
- X
- X if ( length % 2 ) { /* invalid branch after -o */
- X error("Invalid branch range %s after -o", &numrev[0]);
- X return 0;
- X }
- X
- X if ( delrev->code == 1 ) { /* -o -rev */
- X if ( length > 2 ) {
- X temp = searchcutpt( target->num, length-1, gendeltas);
- X cuttail = target->next;
- X }
- X else {
- X temp = searchcutpt(target->num, length, gendeltas);
- X cuttail = target;
- X while( cuttail && ! cmpnumfld(target->num,cuttail->num,1) )
- X cuttail = cuttail->next;
- X }
- X if ( branchpoint(temp, cuttail) ){
- X cuttail = nil;
- X return 0;
- X }
- X delstrt = temp;
- X return 1;
- X }
- X
- X if ( delrev->code == 2 ) { /* -o rev- */
- X if ( length == 2 ) {
- X temp = searchcutpt(target->num, 1,gendeltas);
- X if ( flag)
- X cuttail = target;
- X else
- X cuttail = target->next;
- X }
- X else {
- X if ( flag){
- X cuthead = target;
- X if ( !(temp = target->next) ) return 0;
- X }
- X else
- X temp = searchcutpt(target->num, length, gendeltas);
- X getbranchno(temp->num, &numrev[0]); /* get branch number */
- X target = genrevs(&numrev[0], (char *)nil, (char *)nil, (char *)nil, gendeltas);
- X }
- X if ( branchpoint( temp, cuttail ) ) {
- X cuttail = nil;
- X return 0;
- X }
- X delstrt = temp;
- X return 1;
- X }
- X
- X /* -o rev1-rev2 */
- X if ( ! expandsym(delrev->end, &numrev[0]) ) return 0;
- X if ( length != countnumflds( &numrev[0] ) ) {
- X error("Invalid revision range %s-%s", target->num, &numrev[0]);
- X return 0;
- X }
- X if ( length > 2 && compartial( &numrev[0], target->num, length-1) ) {
- X error("Invalid revision range %s-%s", target->num, &numrev[0]);
- X return 0;
- X }
- X
- X target2 = genrevs( &numrev[0], (char *)nil, (char *)nil, (char *)nil,gendeltas);
- X if ( ! target2 ) return 0;
- X
- X if ( length > 2) { /* delete revisions on branches */
- X if ( cmpnum(target->num, target2->num) > 0) {
- X if ( cmpnum(target2->num, &numrev[0]) )
- X flag = true;
- X else
- X flag = false;
- X temp = target;
- X target = target2;
- X target2 = temp;
- X }
- X if ( flag ) {
- X if ( ! cmpnum(target->num, target2->num) ) {
- X error("Revisions %s-%s don't exist", delrev->strt,delrev->end);
- X return 0;
- X }
- X cuthead = target;
- X temp = target->next;
- X }
- X else
- X temp = searchcutpt(target->num, length, gendeltas);
- X cuttail = target2->next;
- X }
- X else { /* delete revisions on trunk */
- X if ( cmpnum( target->num, target2->num) < 0 ) {
- X temp = target;
- X target = target2;
- X target2 = temp;
- X }
- X else
- X if ( cmpnum(target2->num, &numrev[0]) )
- X flag = true;
- X else
- X flag = false;
- X if ( flag ) {
- X if ( ! cmpnum(target->num, target2->num) ) {
- X error("Revisions %s-%s don't exist", delrev->strt, delrev->end);
- X return 0;
- X }
- X cuttail = target2;
- X }
- X else
- X cuttail = target2->next;
- X temp = searchcutpt(target->num, length, gendeltas);
- X }
- X if ( branchpoint(temp, cuttail) ) {
- X cuttail = nil;
- X return 0;
- X }
- X delstrt = temp;
- X return 1;
- X}
- X
- X
- X
- Xupdateassoc()
- X/* Function: add or delete(if revno is nil) association */
- X/* which is stored in assoclst */
- X
- X{
- X struct Symrev * curassoc;
- X struct assoc * pre, * pt;
- X struct hshentry * target;
- X
- X /* add new associations */
- X curassoc = assoclst;
- X while( curassoc ) {
- X if ( curassoc->revno == nil ) { /* delete symbol */
- X pre = pt = Symbols;
- X while( pt && strcmp(pt->symbol,curassoc->ssymbol) ) {
- X pre = pt;
- X pt = pt->nextassoc;
- X }
- X if ( pt )
- X if ( pre == pt )
- X Symbols = pt->nextassoc;
- X else
- X pre->nextassoc = pt->nextassoc;
- X else
- X warn("Can't delete nonexisting symbol %s",curassoc->ssymbol);
- X }
- X else if ( expandsym( curassoc->revno, &numrev[0] ) ) {
- X /* add symbol */
- X target = (struct hshentry *) talloc(sizeof(struct hshentry));
- X target->num = &numrev[0];
- X VOID addsymbol(target, curassoc->ssymbol, curassoc->override);
- X }
- X curassoc = curassoc->nextsym;
- X }
- X
- X}
- X
- X
- X
- Xupdatelocks()
- X/* Function: remove lock for caller or first lock if unlockcaller==true;
- X * remove locks which are stored in rmvlocklst,
- X * add new locks which are stored in newlocklst,
- X * add lock for Dbranch or Head if lockhead==true.
- X */
- X{
- X struct hshentry *target;
- X struct Lockrev *lockpt;
- X
- X if(unlockcaller == true) { /* find lock for caller */
- X if ( Head ) {
- X if (Locks) {
- X target=findlock(caller,true);
- X if (target==nil) {
- X breaklock(caller, Locks->delta); /* remove most recent lock */
- X } else {
- X diagnose("%s unlocked",target->num);
- X }
- X } else {
- X warn("There are no locks set.");
- X }
- X } else {
- X warn("Can't unlock an empty tree");
- X }
- X }
- X
- X /* remove locks which are stored in rmvlocklst */
- X lockpt = rmvlocklst;
- X while( lockpt ) {
- X if (expandsym(lockpt->revno, numrev)) {
- X target = genrevs(numrev, (char *)nil, (char *)nil, (char *)nil, gendeltas);
- X if ( target )
- X if ( !(countnumflds(numrev)%2) && cmpnum(target->num,numrev))
- X error("Can't unlock nonexisting revision %s",lockpt->revno);
- X else
- X breaklock(caller, target);
- X /* breaklock does its own diagnose */
- X }
- X lockpt = lockpt->nextrev;
- X }
- X
- X /* add new locks which stored in newlocklst */
- X lockpt = newlocklst;
- X while( lockpt ) {
- X setlock(lockpt->revno,caller);
- X lockpt = lockpt->nextrev;
- X }
- X
- X if ( lockhead == true) { /* lock default branch or head */
- X if (Dbranch) {
- X setlock(Dbranch->num,caller);
- X } elsif ( Head) {
- X if (addlock(Head, caller))
- X diagnose("%s locked",Head->num);
- X } else {
- X warn("Can't lock an empty tree");
- X }
- X }
- X
- X}
- X
- X
- X
- Xsetlock(rev,who)
- Xchar * rev, * who;
- X/* Function: Given a revision or branch number, finds the correponding
- X * delta and locks it for who.
- X */
- X{
- X struct lock *lpt;
- X struct hshentry *target;
- X
- X if (expandsym(rev, &numrev[0]) ){
- X target = genrevs(&numrev[0],(char *) nil,(char *) nil,
- X (char *)nil, gendeltas);
- X if ( target )
- X if ( !(countnumflds(&numrev[0])%2) && cmpnum(target->num,&numrev[0]))
- X error("Can't lock nonexisting revision %s",numrev);
- X else
- X if(lpt=addlock(target, who))
- X diagnose("%s locked",lpt->delta->num);
- X }
- X}
- X
- X
- X
- Xrcs_setstate(rev,status)
- Xchar * rev, * status;
- X/* Function: Given a revision or branch number, finds the corresponding delta
- X * and sets its state to status.
- X */
- X{
- X struct hshentry *target;
- X
- X if ( expandsym(rev, &numrev[0]) ) {
- X target = genrevs(&numrev[0],(char *) nil, (char *)nil,
- X (char *) nil, gendeltas);
- X if ( target )
- X if ( !(countnumflds(&numrev[0])%2) && cmpnum(target->num, &numrev[0]) )
- X error("Can't set state of nonexisting revision %s to %s",
- X numrev,status);
- X else
- X target->state = status;
- X }
- X}
- X
- X
- X
- X
- X
- Xbuildeltatext(deltas)
- Xstruct hshentry ** deltas;
- X/* Function: put the delta text on frewrite and make necessary */
- X/* change to delta text */
- X{
- X int i, c, exit_stats;
- X
- X cuttail->selector = DELETE;
- X initeditfiles("/tmp/");
- X scanlogtext(deltas[0], copy);
- X i = 1;
- X if ( cuthead ) {
- X cutfilename=mktempfile("/tmp/", "RCScutXXXXXX");
- X if ( (fcut = fopen(cutfilename, "w")) == NULL) {
- X faterror("Can't open temporary file %s", cutfilename);
- X }
- X
- X while( deltas[i-1] != cuthead ) {
- X scanlogtext(deltas[i++], edit);
- X }
- X
- X finishedit((struct hshentry *)nil); rewind(fcopy);
- X while( (c = getc(fcopy)) != EOF) VOID putc(c, fcut);
- X swapeditfiles(false);
- X ffclose(fcut);
- X }
- X
- X while( deltas[i-1] != cuttail)
- X scanlogtext(deltas[i++], edit);
- X finishedit((struct hshentry *)nil); ffclose(fcopy);
- X
- X if ( cuthead ) {
- X diffilename=mktempfile("/tmp/", "RCSdifXXXXXX");
- X exit_stats = run((char*)nil,diffilename,
- X DIFF,"-n",cutfilename,resultfile,(char*)nil);
- X if (exit_stats != 0 && exit_stats != (1 << BYTESIZ))
- X faterror ("diff failed");
- X if(!putdtext(cuttail->num,curlogmsg,diffilename,frewrite)) return;
- X }
- X else
- X if (!putdtext(cuttail->num,curlogmsg,resultfile,frewrite)) return;
- X
- X scanlogtext((struct hshentry *)nil,empty); /* read the rest of the deltas */
- X}
- X
- X
- X
- Xbuildtree()
- X/* Function: actually removes revisions whose selector field */
- X/* is DELETE, and rebuilds the linkage of deltas. */
- X/* asks for reconfirmation if deleting last revision*/
- X{
- X int c, response;
- X
- X struct hshentry * Delta;
- X struct branchhead *pt, *pre;
- X
- X if ( cuthead )
- X if ( cuthead->next == delstrt )
- X cuthead->next = cuttail;
- X else {
- X pre = pt = cuthead->branches;
- X while( pt && pt->hsh != delstrt ) {
- X pre = pt;
- X pt = pt->nextbranch;
- X }
- X if ( cuttail )
- X pt->hsh = cuttail;
- X else if ( pt == pre )
- X cuthead->branches = pt->nextbranch;
- X else
- X pre->nextbranch = pt->nextbranch;
- X }
- X else {
- X if ( cuttail == nil && !quietflag) {
- X VOID fprintf(stderr,"Do you really want to delete all revisions ?[ny](n): ");
- X c = response = getchar();
- X while( c != EOF && c != '\n') c = getchar();
- X if ( response != 'y' && response != 'Y') {
- X diagnose("No revision deleted");
- X Delta = delstrt;
- X while( Delta) {
- X Delta->selector = 'S';
- X Delta = Delta->next;
- X }
- X return;
- X }
- X }
- X Head = cuttail;
- X }
- X return;
- X}
- X
- X@
- X
- X
- X4.11.2.1
- Xlog
- X@Start of Amiga RCS port branch.
- X@
- Xtext
- X@d6 1
- Xa6 5
- X<<<<<<< rcs.c
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/rcs.c,v 4.11.1.1 89/08/11 01:42:01 rsbx Exp Locker: rsbx $ Purdue CS";
- X=======
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rcs.c,v 1.2 89/09/17 13:35:01 rick Exp $ Purdue CS";
- X>>>>>>> 1.2
- Xa36 11
- X<<<<<<< rcs.c
- X * Revision 4.11.1.1 89/08/11 01:42:01 rsbx
- X * Start of cbmvax RCS source branch.
- X=======
- X * Revision 1.2 89/09/17 13:35:01 rick
- X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
- X * All changes done with conditional compile (#ifdef AMIGA). This version
- X * compiles correctly with Lattice C version 5.02 or later.
- X>>>>>>> 1.2
- X *
- X<<<<<<< rcs.c
- Xa37 3
- X * checked in with -k by rsbx at 89.08.10.16.06.26.
- X *
- X * Revision 4.11 89/05/01 15:12:06 narten
- Xa53 11
- X=======
- X * Revision 1.4 89/09/16 09:42:43 rick
- X * Modified AMIGA changes to work with Lattice C
- X *
- X * Revision 1.3 89/09/10 09:26:56 rick
- X * Moved TARGETDIR to rcs:
- X *
- X * Revision 1.2 88/09/03 15:08:35 rick
- X * Port to AmigaDos. All done with conditional compiles
- X *
- X>>>>>>> 1.2
- Xa133 3
- X#ifdef AMIGA
- X#include "stat.h"
- X#else
- Xa135 9
- X<<<<<<< rcs.c
- X=======
- X#endif
- X#ifdef BSD
- X#include <sysexits.h>
- X#else
- X#define EX_OK 0
- X#endif
- X>>>>>>> 1.2
- Xa578 5
- X#ifdef AMIGA
- X if (finptr != NULL)
- X fclose(finptr);
- X unlink(RCSfilename);
- X#endif
- Xa590 3
- X#ifdef AMIGA
- X result=chmod(RCSfilename,RCSstat.st_attr | S_IWRITE);
- X#else
- Xa591 1
- X#endif
- Xa592 3
- X#ifdef AMIGA
- X result=chmod(RCSfilename,workstat.st_attr | S_IWRITE);
- X#else
- Xa593 1
- X#endif
- Xd673 1
- Xa673 1
- X curpt = pt = pre = nil;
- Xd1007 1
- Xa1007 3
- X#ifdef AMIGA
- X return false;
- X#else
- Xa1057 1
- X#endif AMIGA
- Xa1060 1
- X<<<<<<< rcs.c
- Xa1062 3
- X=======
- Xstruct hshentry * breaklock(who,delta)
- X>>>>>>> 1.2
- Xa1485 3
- X#ifdef AMIGA
- X cutfilename=mktempfile("t:", "RCScutXXXXXX");
- X#else
- Xa1486 1
- X#endif
- Xa1505 3
- X#ifdef AMIGA
- X diffilename=mktempfile("t:", "RCSdifXXXXXX");
- X#else
- Xa1506 1
- X<<<<<<< rcs.c
- Xa1508 5
- X=======
- X#endif
- X VOID sprintf(command, "%s -n %s %s >%s", DIFF,cutfilename, resultfile, diffilename);
- X exit_stats = system (command);
- X>>>>>>> 1.2
- Xa1549 3
- X#ifdef AMIGA
- X fflush(stderr);
- X#endif
- X@
- X
- X
- X4.11.2.2
- Xlog
- X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
- Xsources I have here (and are later than the ones Rick used).
- X@
- Xtext
- X@d6 5
- Xa10 1
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rcs.c,v 4.11.2.1 89/10/13 19:17:47 rsbx Exp Locker: rsbx $ Purdue CS";
- Xd41 1
- Xa41 3
- X * Revision 4.11.2.1 89/10/13 19:17:47 rsbx
- X * Start of Amiga RCS port branch.
- X *
- Xd44 6
- Xd51 1
- Xd72 11
- Xd168 2
- Xd176 1
- Xa1049 1
- X#ifdef AMIGA
- Xd1061 2
- Xa1062 40
- X VOID fprintf(stderr, "Revision %s is already locked by %s.\n", Delta, who);
- X VOID fprintf(stderr, "Do you want to break the lock? [ny](n): ");
- X response=c=getchar();
- X while (!(c==EOF || c=='\n')) c=getchar();/*skip to end of line*/
- X if (response=='\n'||response=='n'||response=='N') return false;
- X
- X /* go ahead with breaking */
- X messagefile=mktempfile("/tmp/", "RCSmailXXXXXX");
- X if ( (mailmess = fopen(messagefile, "w")) == NULL) {
- X faterror("Can't open file %s", messagefile);
- X }
- X
- X VOID fprintf(mailmess, "Subject: Broken lock on %s\n\n",bindex(RCSfilename,'/'));
- X VOID fprintf(mailmess, "Your lock on revision %s of file %s\n",Delta, getfullRCSname());
- X VOID fprintf(mailmess,"has been broken by %s for the following reason:\n",caller);
- X VOID fputs("State the reason for breaking the lock:\n", stderr);
- X VOID fputs("(terminate with ^D or single '.')\n>> ", stderr);
- X
- X old1 = '\n'; old2 = ' ';
- X for (; ;) {
- X c = getchar();
- X if ( c == EOF ) {
- X VOID putc('\n',stderr);
- X VOID fprintf(mailmess, "%c\n", old1);
- X break;
- X }
- X else if ( c == '\n' && old1 == '.' && old2 == '\n')
- X break;
- X else {
- X VOID fputc( old1, mailmess);
- X old2 = old1; old1 = c;
- X if (c== '\n') VOID fputs(">> ", stderr);
- X }
- X }
- X ffclose(mailmess);
- X
- X /* ignore the exit status, even if delivermail unsuccessful */
- X VOID run(messagefile,(char*)nil,
- X#ifdef SENDMAIL
- X "/usr/lib/sendmail",
- Xa1063 24
- X# ifdef DELIVERMAIL
- X "/etc/delivermail","-w",
- X# else
- X "/bin/mail",
- X# endif
- X#endif
- X who,(char*)nil);
- X VOID unlink(messagefile);
- X return(true);
- X}
- X
- X#else
- X
- Xsendmail(Delta, who)
- Xchar * Delta, *who;
- X/* Function: mail to who, informing him that his lock on delta was
- X * broken by caller. Ask first whether to go ahead. Return false on
- X * error or if user decides not to break the lock.
- X */
- X{
- X char * messagefile;
- X int old1, old2, c, response;
- X FILE * mailmess;
- X
- Xd1114 1
- Xa1115 1
- X#endif AMIGA
- Xd1118 1
- Xd1120 4
- Xa1123 1
- Xstatic void breaklock(who,delta)
- Xd1307 1
- Xa1307 1
- X genrevs(&numrev[0], (char *)nil, (char *)nil, (char *)nil, gendeltas);
- Xd1575 1
- Xa1575 2
- X#endif
- X/* <<<<<<< rcs.c */
- Xd1578 2
- Xa1579 1
- X/* =======
- Xd1582 1
- Xa1582 1
- X>>>>>>> 1.2 */
- X@
- X
- X
- X4.11.2.3
- Xlog
- X@Changed file path handling to deal with Amiga file path sematics.
- X@
- Xtext
- X@d6 1
- Xa6 1
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rcs.c,v 4.11.2.2 89/10/15 15:43:36 rsbx Exp $ Purdue CS";
- Xa36 4
- X * Revision 4.11.2.2 89/10/15 15:43:36 rsbx
- X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
- X * sources I have here (and are later than the ones Rick used).
- X *
- Xd160 1
- Xa160 1
- Xextern char * fnamepart();
- Xd1051 1
- Xa1051 1
- X VOID fprintf(mailmess, "Subject: Broken lock on %s\n\n",fnamepart(RCSfilename));
- Xd1116 1
- Xa1116 1
- X VOID fprintf(mailmess, "Subject: Broken lock on %s\n\n",fnamepart(RCSfilename));
- X@
- X
- X
- X4.11.2.4
- Xlog
- X@Changes to sendmail().
- X@
- Xtext
- X@d6 1
- Xa6 1
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rcs.c,v 4.11.2.3 89/10/16 19:06:13 rsbx Exp $ Purdue CS";
- Xa36 3
- X * Revision 4.11.2.3 89/10/16 19:06:13 rsbx
- X * Changed file path handling to deal with Amiga file path sematics.
- X *
- Xd1031 11
- Xd1043 54
- Xa1103 4
- X#ifdef AMIGA
- X VOID fprintf(stderr, "Breaking of locks not supported by this Amiga RCS revision\n");
- X return false;
- X#else
- Xd1158 1
- Xa1159 1
- X}
- Xd1616 1
- Xd1619 4
- X@
- X
- X
- X4.11.2.5
- Xlog
- X@NULL finptr after closing it.
- X@
- Xtext
- X@d6 1
- Xa6 1
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rcs.c,v 4.11.2.4 89/10/17 13:17:35 rsbx Exp $ Purdue CS";
- Xa36 3
- X * Revision 4.11.2.4 89/10/17 13:17:35 rsbx
- X * Changes to sendmail().
- X *
- Xd606 1
- Xa606 1
- X fclose(finptr); finptr = NULL;
- X@
- X
- X
- X4.11.2.6
- Xlog
- X@Changes to make the delete bit to track the write bit. Made protection
- Xbit manipulation less insane.
- X@
- Xtext
- X@d6 1
- Xa6 1
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rcs.c,v 4.11.2.5 89/10/30 13:38:35 rsbx Exp $ Purdue CS";
- Xa36 3
- X * Revision 4.11.2.5 89/10/30 13:38:35 rsbx
- X * NULL finptr after closing it.
- X *
- Xd608 3
- Xa610 8
- X if (finptr != NULL) {
- X fclose(finptr); finptr = NULL;
- X if (chmod(RCSfilename, RCSstat.st_attr|S_IDELETE)<0)
- X warn("Can't adjust mode of %s",RCSfilename);
- X if (unlink(RCSfilename) != 0) { /* Remove failed */
- X error("Can't unlink %s",RCSfilename);
- X }
- X }
- Xd625 1
- Xa625 1
- X result=chmod(RCSfilename,RCSstat.st_attr & ~(S_IWRITE|S_IDELETE));
- Xd631 1
- Xa631 1
- X result=chmod(RCSfilename,workstat.st_attr & ~(S_IWRITE|S_IDELETE));
- Xd1533 1
- Xa1533 1
- X cutfilename=mktempfile("t:", "RCScutXXXXXXXX");
- Xd1535 1
- Xa1535 1
- X cutfilename=mktempfile("/tmp/", "RCScutXXXXXXXX");
- Xd1557 1
- Xa1557 1
- X diffilename=mktempfile("t:", "RCSdifXXXXXXXX");
- Xd1559 1
- Xa1559 1
- X diffilename=mktempfile("/tmp/", "RCSdifXXXXXXXX");
- X@
- X
- X
- X4.11.2.7
- Xlog
- X@Fixed a "/tmp/" that slipped through.
- X@
- Xtext
- X@d6 1
- Xa6 1
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rcs.c,v 4.11.2.6 89/11/01 14:42:32 rsbx Exp $ Purdue CS";
- Xa36 4
- X * Revision 4.11.2.6 89/11/01 14:42:32 rsbx
- X * Changes to make the delete bit to track the write bit. Made protection
- X * bit manipulation less insane.
- X *
- Xa1535 3
- X#ifdef AMIGA
- X initeditfiles("t:");
- X#else
- Xa1536 1
- X#endif
- X@
- X
- X
- X4.11.2.8
- Xlog
- X@WaitChild() on the Amiga returns the completion code from a child process
- Xwithout shifting it up 8 bits like the Unix wait() does.
- X@
- Xtext
- X@d6 1
- Xa6 1
- X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rcs.c,v 4.11.2.7 89/11/05 23:14:17 rsbx Exp $ Purdue CS";
- Xa36 3
- X * Revision 4.11.2.7 89/11/05 23:14:17 rsbx
- X * Fixed a "/tmp/" that slipped through.
- X *
- Xa1578 3
- X#ifdef AMIGA
- X if (exit_stats != 0 && exit_stats != 1)
- X#else
- Xa1579 1
- X#endif
- X@
- X
- X
- X4.11.1.1
- Xlog
- X@Start of cbmvax RCS source branch.
- X@
- Xtext
- X@d6 1
- Xa6 1
- X"$Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/rcs.c,v 4.11 89/05/01 15:12:06 narten Exp $ Purdue CS";
- Xa36 3
- X * Revision 4.11 89/05/01 15:12:06 narten
- X * checked in with -k by rsbx at 89.08.10.16.06.26.
- X *
- X@
- SHAR_EOF
- echo "End of archive 7 (of 14)"
- # if you want to concatenate archives, remove anything after this line
- exit
-